From d4af292c8297fc7796684abe560398ac4c5ce1bc Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 6 Feb 2009 10:36:23 +0000 Subject: [PATCH] Cleanup IOMMU interrupt setup - Check for errors when allocating interrupt vectors - Clean up if interrupt allocation failed - Make sure that the allocated vector is not reused Signed-off-by: Espen Skoglund --- xen/drivers/passthrough/amd/iommu_init.c | 16 ++++++++-------- xen/drivers/passthrough/vtd/iommu.c | 23 ++++++++++++++++------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c index 5b01579845..ecdb5b3b5e 100644 --- a/xen/drivers/passthrough/amd/iommu_init.c +++ b/xen/drivers/passthrough/amd/iommu_init.c @@ -480,15 +480,9 @@ static int set_iommu_interrupt_handler(struct amd_iommu *iommu) int vector, ret; vector = assign_irq_vector(AUTO_ASSIGN); - vector_to_iommu[vector] = iommu; - - /* make irq == vector */ - irq_vector[vector] = vector; - vector_irq[vector] = vector; - - if ( !vector ) + if ( vector <= 0 ) { - amd_iov_error("no vectors\n"); + gdprintk(XENLOG_ERR VTDPREFIX, "IOMMU: no vectors\n"); return 0; } @@ -496,9 +490,15 @@ static int set_iommu_interrupt_handler(struct amd_iommu *iommu) ret = request_irq(vector, amd_iommu_page_fault, 0, "amd_iommu", iommu); if ( ret ) { + irq_desc[vector].handler = &no_irq_type; + free_irq_vector(vector); amd_iov_error("can't request irq\n"); return 0; } + + /* Make sure that vector is never re-used. */ + vector_irq[vector] = NEVER_ASSIGN; + vector_to_iommu[vector] = iommu; iommu->vector = vector; return vector; } diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index 9e76597d86..cec1e9db43 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -875,13 +875,7 @@ int iommu_set_interrupt(struct iommu *iommu) int vector, ret; vector = assign_irq_vector(AUTO_ASSIGN); - vector_to_iommu[vector] = iommu; - - /* VT-d fault is a MSI, make irq == vector */ - irq_vector[vector] = vector; - vector_irq[vector] = vector; - - if ( !vector ) + if ( vector <= 0 ) { gdprintk(XENLOG_ERR VTDPREFIX, "IOMMU: no vectors\n"); return -EINVAL; @@ -890,7 +884,17 @@ int iommu_set_interrupt(struct iommu *iommu) irq_desc[vector].handler = &dma_msi_type; ret = request_irq(vector, iommu_page_fault, 0, "dmar", iommu); if ( ret ) + { + irq_desc[vector].handler = &no_irq_type; + free_irq_vector(vector); gdprintk(XENLOG_ERR VTDPREFIX, "IOMMU: can't request irq\n"); + return ret; + } + + /* Make sure that vector is never re-used. */ + vector_irq[vector] = NEVER_ASSIGN; + vector_to_iommu[vector] = iommu; + return vector; } @@ -1677,6 +1681,11 @@ static int init_vtd_hw(void) } vector = iommu_set_interrupt(iommu); + if ( vector < 0 ) + { + gdprintk(XENLOG_ERR VTDPREFIX, "IOMMU: interrupt setup failed\n"); + return vector; + } dma_msi_data_init(iommu, vector); dma_msi_addr_init(iommu, cpu_physical_id(first_cpu(cpu_online_map))); iommu->vector = vector; -- 2.30.2